﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using K9Nano.Dependency;
using K9Nano.Share.Exceptions;

namespace K9Nano.Events
{
    public class DefaultTypeEventNameGenerator : ITypeEventNameGenerator, ISingletonDependency
    {
        private readonly ConcurrentDictionary<Type, string> _cache;

        public DefaultTypeEventNameGenerator()
        {
            _cache = new ConcurrentDictionary<Type, string>();
        }

        public string Generate(Type type)
        {
            if (_cache.ContainsKey(type)) return _cache[type];

            if (type.IsGenericTypeDefinition)
            {
                throw new K9Exception("Type can not be Generic Type.");
            }

            var name = type.FullName;
            if (string.IsNullOrEmpty(name))
            {
                throw new K9Exception("Type must have FullName.");
            }

            if (type.IsGenericType)
            {
                name = name.Substring(0, name.IndexOf('`'));
                var gTypeNames = new List<string>(type.GenericTypeArguments.Length);
                foreach (var gType in type.GenericTypeArguments)
                {
                    if (gType.IsGenericType || gType.IsGenericTypeDefinition) // 暂不支持
                    {
                        throw new K9Exception($"Generic type argument can not be generic type: {gType}");
                    }
                    gTypeNames.Add(gType.FullName);
                }

                name = $"{name}<{string.Join('+', gTypeNames)}>";
            }

            if (_cache.Values.Contains(name))
            {
                throw new K9Exception($"Event name has already exists: {type}, {name}");
            }
            _cache.TryAdd(type, name);
            return name;
        }
    }
}